package cn.tedu.v6;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;


/**
 * Version 6  在线用户列表
 */

public class Server {
    private ServerSocket serverSocket;
    private static final Integer PORT=4545;
    private List<PrintWriter> allOut=new ArrayList<>();
    private Map<String,String> userDataBase;
    //1.私有化一个集合保存用户名--onlineUsers
    private List<String> onlineUsers = new ArrayList<>();






    public Server() {
        try {
            serverSocket=new ServerSocket(PORT);
            userDataBase=new HashMap<>();
            userDataBase.put("123","567");
            userDataBase.put("234","678");
        } catch (BindException e) {
            System.out.println("端口号重复申请，建议换个端口号");
        }catch (IOException e){
            System.out.println("申请端口号失败---");
        }
    }
    public void start(){
        try {
            while (true) {
                System.out.println("-----等待客户端链接-----");
                Socket socket = serverSocket.accept();
                System.out.println("----客户端链接成功----");
                new Thread(new ClientHandler(socket)).start();
            }
        } catch (IOException e) {
            System.out.println("服务器端通讯断开了");
        }finally {
            if (serverSocket!=null&&!serverSocket.isClosed()){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    System.out.println("服务器关闭失败");
                }
            }

        }
    }
    public static void main(String[] args){
        new Server().start();
    }
     private synchronized void broadcastMessage(String message){
         for (PrintWriter pw: allOut){
             pw.println("消息广播："+message);
                 }
         }

    //2.封装一个方法：同步转发给所有客户端消息：“在线用户：”+onlineUsers
    //updateOnlineUsers  更新在线人名单的方法：“在线用户：”+onlineUsers
    //字符串：String userList="在线用户"+String.join("、",onlineUsers)
    //UserLine 写出给所有客户端
     public Map<String, Socket> updateOnlineUsers() {
             String usersList = "在线用户：" + onlineUsers;
             for (PrintWriter writer : allOut) {
                 writer.println(usersList);
             }
             return null;
     }






     private void closeResources(BufferedReader br,PrintWriter pw,Socket socket){
         if(br!=null);
         try {
             br.close();
         } catch (IOException e) {
             System.out.println("结束通讯：关闭失败：");
         }

         if (pw!=null) pw.close();
         if (socket!=null&&!socket.isClosed()) {
             try {
                 socket.close();
             } catch (IOException e) {
                 System.out.println("通讯关闭失败");
             }
         }
     }





    private class ClientHandler implements Runnable{
        private Socket socket;
        private String ip;
        private BufferedReader br;
        private PrintWriter pw;
        private String username;
        private String password;

        public ClientHandler(Socket s){
            this.socket=s;
            ip=socket.getInetAddress().getHostAddress();

            try {
                br=new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
                pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF8")),true);

                synchronized (allOut) {
                    allOut.add(pw);
                }

            } catch (IOException e) {
                System.out.println("客户端断开通讯~~");
            }
        }

        private boolean Login(String user,String pass){

            return userDataBase.containsKey(user)&&userDataBase.get(user).equals(pass);
        }

        private void handlerChat(){
            new Thread(()->{
                try {
                    String message;
                    while ((message = br.readLine()) != null) {
                        System.out.println(username +"客户端说:"+ message);
                        if (message.equalsIgnoreCase("exit")) {
                            System.out.println("111111111111");
                            pw.println("服务器退出");
                            break;
                        }
//                        if (message.equalsIgnoreCase("退出")){
//                            pw.println("退出");
//                        }
                            broadcastMessage(message);
                        }
                }catch (IOException e) {
                        System.out.println(username + "已退出聊天室");
                        System.out.println("客户端读入失败");
                    }
            }).start();

            Scanner input=new Scanner(System.in);
            while (true) {
                System.out.println("服务器请输入：");
                String say=input.nextLine();
                pw.println("服务器说："+say);
            }
        }

        public void run() {
            try {

                pw.println("请输入用户名：");
                username=br.readLine();

                pw.println("请输入密码：");
                password=br.readLine();
                if (Login(username,password)){
                    pw.println("登录成功，欢迎进入聊天室");
                    //3.所有的用户添加至集合中【同步块：监视登录集合】
                    // 3.1转发在线用户方法
                        synchronized (onlineUsers){
                            onlineUsers.add(username);
                        }
                        updateOnlineUsers();
                        handlerChat();






                }else {
                    pw.println("登陆失败，用户名或者密码错误！");
                    socket.close();
                }
            }catch (NullPointerException e){
                System.out.println("IO流传入对象，有对象可能为null，立马核对，建议：查看try块中对象可能赋值为null");
            }catch (IOException e){
                System.out.println("服务器端断开连接");
            }finally {
                //4.客户端断开连接，移除当前集合【同步】
                boolean removedFromOnlineUsers=false;
                synchronized (onlineUsers){
                    if (username!= null && onlineUsers.contains(username)) {
                        try {
                            if ("exit".equalsIgnoreCase(br.readLine())) {
                                System.out.println(username + "退出登录，IP是：" + ip);
                                onlineUsers.remove(username);
                                removedFromOnlineUsers = true;
                                handlerChat();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
//                        try {
//                            if ("exit".equalsIgnoreCase(br.readLine())){
//                                System.out.println(username+"已退出聊天室3");
//                                onlineUsers.remove(username);
//                                removedFromOnlineUsers=true;
//                            }
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
                    }

                }


                allOut.remove(pw);
                    if (removedFromOnlineUsers){
                        updateOnlineUsers();
                }

            }
        }
    }
}

